// 标准输出和报错机制
#include <stdarg.h>
#include "lib/print.h"
#include "lib/lock.h"
#include "dev/uart.h"
#include "riscv.h"

volatile int panicked = 0;

// 声明标志，用于确保printf的初始化
volatile static int started = 0;
spinlock_t print_lock;  // 避免与函数名冲突

// 需要提前声明子函数
void print_int(int num);
void print_hex(unsigned int num);
void print_ptr(void *ptr);
void print_str(const char *s);

// 1. init函数用于初始化打印系统，可以用来初始化自旋锁
void print_init() {
    uart_init();  // 初始化 UART
    spinlock_init(&print_lock, "print_lock");  // 初始化自旋锁
    started = 1;  // 标记 printf 已经可以使用
}

// Print to the console. only understands %d, %x, %p, %s.
// 2. printf函数是核心输出函数，负责格式化字符串并输出至串口或其他设备
void printf(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);

    // 获取自旋锁，防止并发打印混乱
    spinlock_acquire(&print_lock);

    // 禁用中断，防止中断打断输出
    push_off();

    for (const char *p = fmt; *p != '\0'; p++) {
        if (*p != '%') {
            uart_putc_sync(*p);  // 输出普通字符
            continue;
        }

        p++;  // 跳过 '%' 符号

        switch (*p) {
        case 'd': {
            int num = va_arg(args, int);
            print_int(num);  // 输出整数
            break;
        }
        case 'x': {
            unsigned int num = va_arg(args, unsigned int);
            print_hex(num);  // 输出十六进制
            break;
        }
        case 'p': {
            void *ptr = va_arg(args, void*);
            print_ptr(ptr);  // 输出指针
            break;
        }
        case 's': {
            const char *str = va_arg(args, const char*);
            print_str(str);  // 输出字符串
            break;
        }
        default:
            uart_putc_sync('%');  // 输出未知的格式符号
            uart_putc_sync(*p);
            break;
        }
    }

    va_end(args);

    // 恢复中断
    pop_off();

    // 释放自旋锁
    spinlock_release(&print_lock);
}

// 2.1 输出整数
void print_int(int num) {
    char buf[16];
    int i = 0, is_negative = 0;

    if (num < 0) {
        is_negative = 1;
        num = -num;
    }

    do {
        buf[i++] = (num % 10) + '0';
        num /= 10;
    } while (num > 0);

    if (is_negative) {
        buf[i++] = '-';
    }

    while (--i >= 0) {
        uart_putc_sync(buf[i]);  // 输出每个字符
    }
}

// 2.2 输出十六进制数
void print_hex(unsigned int num) {
    char hex_digits[] = "0123456789abcdef";
    char buf[16];
    int i = 0;

    do {
        buf[i++] = hex_digits[num % 16];
        num /= 16;
    } while (num > 0);

    uart_putc_sync('0');  // 输出 "0x" 前缀
    uart_putc_sync('x');

    while (--i >= 0) {
        uart_putc_sync(buf[i]);  // 输出每个字符
    }
}

// 2.3 输出指针
void print_ptr(void *ptr) {
    print_hex((unsigned long)ptr);  // 直接调用十六进制输出函数
}

// 2.4 输出字符串
void print_str(const char *s) {
    while (*s != '\0') {
        uart_putc_sync(*s++);  // 输出每个字符
    }
}

// 系统崩溃时调用
void panic(const char *s) {
    push_off();  // 禁用中断

    // 直接输出 panic 信息，避免调用printf
    uart_puts("Panic: ");

    print_str(s);
    uart_putc_sync('\n');

    // 停止系统或进入死循环
    for (;;) {}
}

// 断言函数
void assert(bool condition, const char *msg) {
    if (!condition) {
        panic(msg);  // 如果条件不满足，调用 panic
    }
}